`timescale 1ns / 1ps

`include "MIPSCPU_COMMON.vh"

module InstructionDecode(
	id_enable,
	instr,
	id_out_enable,
	op_type,
	op_subtype,
	reg1_read_enable,
	reg1_read_addr,
	reg1_read_hi_enable,
	reg1_read_lo_enable,
	reg2_read_enable,
	reg2_read_addr,
	reg_write_enable,
	reg_write_addr,
	reg_write_hi_enable,
	reg_write_lo_enable,
	imm_enable,
	imm_value
    );

	input id_enable;
	input[`DATA_WIDTH - 1 : 0] instr;
	output reg id_out_enable;
	output reg[`OPERATION_TYPE_WIDTH - 1 : 0] op_type;
	output reg[`OPERATION_SUBTYPE_WIDTH - 1 : 0] op_subtype;
	output reg reg1_read_enable, reg2_read_enable, reg_write_enable;
	output reg reg1_read_hi_enable, reg1_read_lo_enable, reg_write_hi_enable, reg_write_lo_enable;
	output reg[`REGISTER_ADDRESS_WIDTH - 1 : 0] reg1_read_addr, reg2_read_addr, reg_write_addr;
	output reg imm_enable;
	output reg[`DATA_WIDTH - 1 : 0] imm_value;
	
	wire[`INSTRUCTION_OP_WIDTH - 1 : 0] tmp_op;
	wire[`REGISTER_ADDRESS_WIDTH - 1 : 0] tmp_rs, tmp_rt, tmp_rd;
	wire[`INSTRUCTION_SA_WIDTH - 1 : 0] tmp_sa;
	wire[`INSTRUCTION_FUNC_WIDTH - 1 : 0] tmp_func;
	wire[`INSTRUCTION_IMM_WIDTH - 1 : 0] tmp_imm;
	wire[`INSTRUCTION_J_ADDR_WIDTH - 1 : 0] tmp_j_addr;
	
	assign tmp_op = instr[`INSTRUCTION_OP_BEGIN : `INSTRUCTION_OP_END];
	assign tmp_rs = instr[`INSTRUCTION_RS_BEGIN : `INSTRUCTION_RS_END];
	assign tmp_rt = instr[`INSTRUCTION_RT_BEGIN : `INSTRUCTION_RT_END];
	assign tmp_rd = instr[`INSTRUCTION_RD_BEGIN : `INSTRUCTION_RD_END];
	assign tmp_sa = instr[`INSTRUCTION_SA_BEGIN : `INSTRUCTION_SA_END];
	assign tmp_func = instr[`INSTRUCTION_FUNC_BEGIN : `INSTRUCTION_FUNC_END];
	assign tmp_imm = instr[`INSTRUCTION_IMM_BEGIN : `INSTRUCTION_IMM_END];
	assign tmp_j_addr = instr[`INSTRUCTION_J_ADDR_BEGIN : `INSTRUCTION_J_ADDR_END];
	
	wire [`DATA_WIDTH - 1 : 0] tmp_sa_ext, tmp_imm_signext, tmp_imm_zeroext, tmp_j_addr_ext;
	assign tmp_sa_ext = {`INSTRUCTION_SA_EXT_WIDTH'b0, tmp_sa};
	assign tmp_imm_signext = {{`INSTRUCTION_IMM_EXT_WIDTH{tmp_imm[`INSTRUCTION_IMM_WIDTH - 1]}}, tmp_imm};
	assign tmp_imm_zeroext = {`INSTRUCTION_IMM_EXT_WIDTH'b0, tmp_imm};
	assign tmp_j_addr_ext = {`INSTRUCTION_J_ADDR_EXT_WIDTH'b0, tmp_j_addr};
	
	always @(*)
	begin
		id_out_enable <= id_enable;
		if (id_enable) begin
			if (instr == `INSTRUCTION_NOP) begin
				op_type <= `OPERATION_TYPE_NOP;
				op_subtype <= `OPERATION_SUBTYPE_NOP;
				reg1_read_enable <= 0;
				reg1_read_addr <= 0;
				reg1_read_hi_enable <= 0;
				reg1_read_lo_enable <= 0;
				reg2_read_enable <= 0;
				reg2_read_addr <= 0;
				reg_write_enable <= 0;
				reg_write_addr <= 0;
				reg_write_hi_enable <= 0;
				reg_write_lo_enable <= 0;
				imm_enable <= 0;
				imm_value <= 0;
			end else if (tmp_op == `INSTRUCTION_OP_SPECIAL) begin
				if (tmp_func == `INSTRUCTION_FUNC_ADDU) begin
					op_type <= `OPERATION_TYPE_ALU;
					op_subtype <= `OPERATION_SUBTYPE_ADD;
					reg1_read_enable <= 1;
					reg1_read_addr <= tmp_rs;
					reg1_read_hi_enable <= 0;
					reg1_read_lo_enable <= 0;
					reg2_read_enable <= 1;
					reg2_read_addr <= tmp_rt;
					reg_write_enable <= 1;
					reg_write_addr <= tmp_rd;
					reg_write_hi_enable <= 0;
					reg_write_lo_enable <= 0;
					imm_enable <= 0;
					imm_value <= 0;
				end else if (tmp_func == `INSTRUCTION_FUNC_SLT) begin
					op_type <= `OPERATION_TYPE_ALU;
					op_subtype <= `OPERATION_SUBTYPE_LESS;
					reg1_read_enable <= 1;
					reg1_read_addr <= tmp_rs;
					reg1_read_hi_enable <= 0;
					reg1_read_lo_enable <= 0;
					reg2_read_enable <= 1;
					reg2_read_addr <= tmp_rt;
					reg_write_enable <= 1;
					reg_write_addr <= tmp_rd;
					reg_write_hi_enable <= 0;
					reg_write_lo_enable <= 0;
					imm_enable <= 0;
					imm_value <= 0;
				end else if (tmp_func == `INSTRUCTION_FUNC_SLTU) begin
					op_type <= `OPERATION_TYPE_ALU;
					op_subtype <= `OPERATION_SUBTYPE_LESS_UNSIGNED;
					reg1_read_enable <= 1;
					reg1_read_addr <= tmp_rs;
					reg1_read_hi_enable <= 0;
					reg1_read_lo_enable <= 0;
					reg2_read_enable <= 1;
					reg2_read_addr <= tmp_rt;
					reg_write_enable <= 1;
					reg_write_addr <= tmp_rd;
					reg_write_hi_enable <= 0;
					reg_write_lo_enable <= 0;
					imm_enable <= 0;
					imm_value <= 0;
				end else if (tmp_func == `INSTRUCTION_FUNC_SUBU) begin
					op_type <= `OPERATION_TYPE_ALU;
					op_subtype <= `OPERATION_SUBTYPE_SUB;
					reg1_read_enable <= 1;
					reg1_read_addr <= tmp_rs;
					reg1_read_hi_enable <= 0;
					reg1_read_lo_enable <= 0;
					reg2_read_enable <= 1;
					reg2_read_addr <= tmp_rt;
					reg_write_enable <= 1;
					reg_write_addr <= tmp_rd;
					reg_write_hi_enable <= 0;
					reg_write_lo_enable <= 0;
					imm_enable <= 0;
					imm_value <= 0;
				end else if (tmp_func == `INSTRUCTION_FUNC_MFLO) begin
					op_type <= `OPERATION_TYPE_ALU;
					op_subtype <= `OPERATION_SUBTYPE_GET;
					reg1_read_enable <= 1;
					reg1_read_addr <= 0;
					reg1_read_hi_enable <= 0;
					reg1_read_lo_enable <= 1;
					reg2_read_enable <= 0;
					reg2_read_addr <= 0;
					reg_write_enable <= 1;
					reg_write_addr <= tmp_rd;
					reg_write_hi_enable <= 0;
					reg_write_lo_enable <= 0;
					imm_enable <= 0;
					imm_value <= 0;
				end else if (tmp_func == `INSTRUCTION_FUNC_MFHI) begin
					op_type <= `OPERATION_TYPE_ALU;
					op_subtype <= `OPERATION_SUBTYPE_GET;
					reg1_read_enable <= 1;
					reg1_read_addr <= 0;
					reg1_read_hi_enable <= 1;
					reg1_read_lo_enable <= 0;
					reg2_read_enable <= 0;
					reg2_read_addr <= 0;
					reg_write_enable <= 1;
					reg_write_addr <= tmp_rd;
					reg_write_hi_enable <= 0;
					reg_write_lo_enable <= 0;
					imm_enable <= 0;
					imm_value <= 0;
				end else if (tmp_func == `INSTRUCTION_FUNC_MTLO) begin
					op_type <= `OPERATION_TYPE_ALU;
					op_subtype <= `OPERATION_SUBTYPE_GET;
					reg1_read_enable <= 1;
					reg1_read_addr <= tmp_rs;
					reg1_read_hi_enable <= 0;
					reg1_read_lo_enable <= 0;
					reg2_read_enable <= 0;
					reg2_read_addr <= 0;
					reg_write_enable <= 1;
					reg_write_addr <= 0;
					reg_write_hi_enable <= 0;
					reg_write_lo_enable <= 1;
					imm_enable <= 0;
					imm_value <= 0;
				end else if (tmp_func == `INSTRUCTION_FUNC_MTHI) begin
					op_type <= `OPERATION_TYPE_ALU;
					op_subtype <= `OPERATION_SUBTYPE_GET;
					reg1_read_enable <= 1;
					reg1_read_addr <= tmp_rs;
					reg1_read_hi_enable <= 0;
					reg1_read_lo_enable <= 0;
					reg2_read_enable <= 0;
					reg2_read_addr <= 0;
					reg_write_enable <= 1;
					reg_write_addr <= 0;
					reg_write_hi_enable <= 1;
					reg_write_lo_enable <= 0;
					imm_enable <= 0;
					imm_value <= 0;
				end else if (tmp_func == `INSTRUCTION_FUNC_JALR) begin
					op_type <= `OPERATION_TYPE_JUMP;
					op_subtype <= `OPERATION_SUBTYPE_NOP;
					reg1_read_enable <= 1;
					reg1_read_addr <= tmp_rs;
					reg1_read_hi_enable <= 0;
					reg1_read_lo_enable <= 0;
					reg2_read_enable <= 0;
					reg2_read_addr <= 0;
					reg_write_enable <= 1;
					reg_write_addr <=
						(tmp_rd == `MIPS_CPU_REGISTER_ZERO_NO
						? `MIPS_CPU_REGISTER_RA_NO
						: tmp_rd);
					reg_write_hi_enable <= 0;
					reg_write_lo_enable <= 0;
					imm_enable <= 0;
					imm_value <= 0;
				end else if (tmp_func == `INSTRUCTION_FUNC_JR) begin
					op_type <= `OPERATION_TYPE_JUMP;
					op_subtype <= `OPERATION_SUBTYPE_NOP;
					reg1_read_enable <= 1;
					reg1_read_addr <= tmp_rs;
					reg1_read_hi_enable <= 0;
					reg1_read_lo_enable <= 0;
					reg2_read_enable <= 0;
					reg2_read_addr <= 0;
					reg_write_enable <= 0;
					reg_write_addr <= 0;
					reg_write_hi_enable <= 0;
					reg_write_lo_enable <= 0;
					imm_enable <= 0;
					imm_value <= 0;
				end else if (tmp_func == `INSTRUCTION_FUNC_AND) begin
					op_type <= `OPERATION_TYPE_ALU;
					op_subtype <= `OPERATION_SUBTYPE_AND;
					reg1_read_enable <= 1;
					reg1_read_addr <= tmp_rs;
					reg1_read_hi_enable <= 0;
					reg1_read_lo_enable <= 0;
					reg2_read_enable <= 1;
					reg2_read_addr <= tmp_rt;
					reg_write_enable <= 1;
					reg_write_addr <= tmp_rd;
					reg_write_hi_enable <= 0;
					reg_write_lo_enable <= 0;
					imm_enable <= 0;
					imm_value <= 0;
				end else if (tmp_func == `INSTRUCTION_FUNC_NOR) begin
					op_type <= `OPERATION_TYPE_ALU;
					op_subtype <= `OPERATION_SUBTYPE_NOR;
					reg1_read_enable <= 1;
					reg1_read_addr <= tmp_rs;
					reg1_read_hi_enable <= 0;
					reg1_read_lo_enable <= 0;
					reg2_read_enable <= 1;
					reg2_read_addr <= tmp_rt;
					reg_write_enable <= 1;
					reg_write_addr <= tmp_rd;
					reg_write_hi_enable <= 0;
					reg_write_lo_enable <= 0;
					imm_enable <= 0;
					imm_value <= 0;
				end else if (tmp_func == `INSTRUCTION_FUNC_OR) begin
					op_type <= `OPERATION_TYPE_ALU;
					op_subtype <= `OPERATION_SUBTYPE_OR;
					reg1_read_enable <= 1;
					reg1_read_addr <= tmp_rs;
					reg1_read_hi_enable <= 0;
					reg1_read_lo_enable <= 0;
					reg2_read_enable <= 1;
					reg2_read_addr <= tmp_rt;
					reg_write_enable <= 1;
					reg_write_addr <= tmp_rd;
					reg_write_hi_enable <= 0;
					reg_write_lo_enable <= 0;
					imm_enable <= 0;
					imm_value <= 0;
				end else if (tmp_func == `INSTRUCTION_FUNC_XOR) begin
					op_type <= `OPERATION_TYPE_ALU;
					op_subtype <= `OPERATION_SUBTYPE_XOR;
					reg1_read_enable <= 1;
					reg1_read_addr <= tmp_rs;
					reg1_read_hi_enable <= 0;
					reg1_read_lo_enable <= 0;
					reg2_read_enable <= 1;
					reg2_read_addr <= tmp_rt;
					reg_write_enable <= 1;
					reg_write_addr <= tmp_rd;
					reg_write_hi_enable <= 0;
					reg_write_lo_enable <= 0;
					imm_enable <= 0;
					imm_value <= 0;
				end else if (tmp_func == `INSTRUCTION_FUNC_SLL) begin
					op_type <= `OPERATION_TYPE_ALU;
					op_subtype <= `OPERATION_SUBTYPE_SLL;
					reg1_read_enable <= 1;
					reg1_read_addr <= tmp_rt;
					reg1_read_hi_enable <= 0;
					reg1_read_lo_enable <= 0;
					reg2_read_enable <= 0;
					reg2_read_addr <= 0;
					reg_write_enable <= 1;
					reg_write_addr <= tmp_rd;
					reg_write_hi_enable <= 0;
					reg_write_lo_enable <= 0;
					imm_enable <= 1;
					imm_value <= tmp_sa_ext;
				end else if (tmp_func == `INSTRUCTION_FUNC_SLLV) begin
					op_type <= `OPERATION_TYPE_ALU;
					op_subtype <= `OPERATION_SUBTYPE_SLL;
					reg1_read_enable <= 1;
					reg1_read_addr <= tmp_rt;
					reg1_read_hi_enable <= 0;
					reg1_read_lo_enable <= 0;
					reg2_read_enable <= 1;
					reg2_read_addr <= tmp_rs;
					reg_write_enable <= 1;
					reg_write_addr <= tmp_rd;
					reg_write_hi_enable <= 0;
					reg_write_lo_enable <= 0;
					imm_enable <= 0;
					imm_value <= 0;
				end else if (tmp_func == `INSTRUCTION_FUNC_SRA) begin
					op_type <= `OPERATION_TYPE_ALU;
					op_subtype <= `OPERATION_SUBTYPE_SRA;
					reg1_read_enable <= 1;
					reg1_read_addr <= tmp_rt;
					reg1_read_hi_enable <= 0;
					reg1_read_lo_enable <= 0;
					reg2_read_enable <= 0;
					reg2_read_addr <= 0;
					reg_write_enable <= 1;
					reg_write_addr <= tmp_rd;
					reg_write_hi_enable <= 0;
					reg_write_lo_enable <= 0;
					imm_enable <= 1;
					imm_value <= tmp_sa_ext;
				end else if (tmp_func == `INSTRUCTION_FUNC_SRAV) begin
					op_type <= `OPERATION_TYPE_ALU;
					op_subtype <= `OPERATION_SUBTYPE_SRA;
					reg1_read_enable <= 1;
					reg1_read_addr <= tmp_rt;
					reg1_read_hi_enable <= 0;
					reg1_read_lo_enable <= 0;
					reg2_read_enable <= 1;
					reg2_read_addr <= tmp_rs;
					reg_write_enable <= 1;
					reg_write_addr <= tmp_rd;
					reg_write_hi_enable <= 0;
					reg_write_lo_enable <= 0;
					imm_enable <= 0;
					imm_value <= 0;
				end else if (tmp_func == `INSTRUCTION_FUNC_SRL) begin
					op_type <= `OPERATION_TYPE_ALU;
					op_subtype <= `OPERATION_SUBTYPE_SRL;
					reg1_read_enable <= 1;
					reg1_read_addr <= tmp_rt;
					reg1_read_hi_enable <= 0;
					reg1_read_lo_enable <= 0;
					reg2_read_enable <= 0;
					reg2_read_addr <= 0;
					reg_write_enable <= 1;
					reg_write_addr <= tmp_rd;
					reg_write_hi_enable <= 0;
					reg_write_lo_enable <= 0;
					imm_enable <= 1;
					imm_value <= tmp_sa_ext;
				end else if (tmp_func == `INSTRUCTION_FUNC_SRLV) begin
					op_type <= `OPERATION_TYPE_ALU;
					op_subtype <= `OPERATION_SUBTYPE_SRL;
					reg1_read_enable <= 1;
					reg1_read_addr <= tmp_rt;
					reg1_read_hi_enable <= 0;
					reg1_read_lo_enable <= 0;
					reg2_read_enable <= 1;
					reg2_read_addr <= tmp_rs;
					reg_write_enable <= 1;
					reg_write_addr <= tmp_rd;
					reg_write_hi_enable <= 0;
					reg_write_lo_enable <= 0;
					imm_enable <= 0;
					imm_value <= 0;
				end else begin
					op_type <= `OPERATION_TYPE_NOP;
					op_subtype <= `OPERATION_SUBTYPE_NOP;
					reg1_read_enable <= 0;
					reg1_read_addr <= 0;
					reg1_read_hi_enable <= 0;
					reg1_read_lo_enable <= 0;
					reg2_read_enable <= 0;
					reg2_read_addr <= 0;
					reg_write_enable <= 0;
					reg_write_addr <= 0;
					reg_write_hi_enable <= 0;
					reg_write_lo_enable <= 0;
					imm_enable <= 0;
					imm_value <= 0;
				end
			end else if (tmp_op == `INSTRUCTION_OP_ADDIU) begin
				op_type <= `OPERATION_TYPE_ALU;
				op_subtype <= `OPERATION_SUBTYPE_ADD;
				reg1_read_enable <= 1;
				reg1_read_addr <= tmp_rs;
				reg1_read_hi_enable <= 0;
				reg1_read_lo_enable <= 0;
				reg2_read_enable <= 0;
				reg2_read_addr <= 0;
				reg_write_enable <= 1;
				reg_write_addr <= tmp_rt;
				reg_write_hi_enable <= 0;
				reg_write_lo_enable <= 0;
				imm_enable <= 1;
				imm_value <= tmp_imm_signext;
			end else if (tmp_op == `INSTRUCTION_OP_SLTI) begin
				op_type <= `OPERATION_TYPE_ALU;
				op_subtype <= `OPERATION_SUBTYPE_LESS;
				reg1_read_enable <= 1;
				reg1_read_addr <= tmp_rs;
				reg1_read_hi_enable <= 0;
				reg1_read_lo_enable <= 0;
				reg2_read_enable <= 0;
				reg2_read_addr <= 0;
				reg_write_enable <= 1;
				reg_write_addr <= tmp_rt;
				reg_write_hi_enable <= 0;
				reg_write_lo_enable <= 0;
				imm_enable <= 1;
				imm_value <= tmp_imm_signext;
			end else if (tmp_op == `INSTRUCTION_OP_SLTIU) begin
				op_type <= `OPERATION_TYPE_ALU;
				op_subtype <= `OPERATION_SUBTYPE_LESS_UNSIGNED;
				reg1_read_enable <= 1;
				reg1_read_addr <= tmp_rs;
				reg1_read_hi_enable <= 0;
				reg1_read_lo_enable <= 0;
				reg2_read_enable <= 0;
				reg2_read_addr <= 0;
				reg_write_enable <= 1;
				reg_write_addr <= tmp_rt;
				reg_write_hi_enable <= 0;
				reg_write_lo_enable <= 0;
				imm_enable <= 1;
				imm_value <= tmp_imm_zeroext;
			end else if (tmp_op == `INSTRUCTION_OP_BEQ) begin
				op_type <= `OPERATION_TYPE_BRANCH;
				op_subtype <= `OPERATION_SUBTYPE_EQUAL;
				reg1_read_enable <= 1;
				reg1_read_addr <= tmp_rs;
				reg1_read_hi_enable <= 0;
				reg1_read_lo_enable <= 0;
				reg2_read_enable <= 1;
				reg2_read_addr <= tmp_rt;
				reg_write_enable <= 0;
				reg_write_addr <= 0;
				reg_write_hi_enable <= 0;
				reg_write_lo_enable <= 0;
				imm_enable <= 1;
				imm_value <= tmp_imm_signext << 2;
			end else if (tmp_op == `INSTRUCTION_OP_REGIMM) begin
				if (tmp_rt == `INSTRUCTION_RT_BGEZ) begin
					op_type <= `OPERATION_TYPE_BRANCH;
					op_subtype <= `OPERATION_SUBTYPE_GREATER_EQUAL;
					reg1_read_enable <= 1;
					reg1_read_addr <= tmp_rs;
					reg1_read_hi_enable <= 0;
					reg1_read_lo_enable <= 0;
					reg2_read_enable <= 0;
					reg2_read_addr <= 0;
					reg_write_enable <= 0;
					reg_write_addr <= 0;
					reg_write_hi_enable <= 0;
					reg_write_lo_enable <= 0;
					imm_enable <= 1;
					imm_value <= tmp_imm_signext << 2;
				end else if (tmp_rt == `INSTRUCTION_RT_BGEZAL) begin
					op_type <= `OPERATION_TYPE_BRANCH;
					op_subtype <= `OPERATION_SUBTYPE_GREATER_EQUAL;
					reg1_read_enable <= 1;
					reg1_read_addr <= tmp_rs;
					reg1_read_hi_enable <= 0;
					reg1_read_lo_enable <= 0;
					reg2_read_enable <= 0;
					reg2_read_addr <= 0;
					reg_write_enable <= 1;
					reg_write_addr <= `MIPS_CPU_REGISTER_RA_NO;
					reg_write_hi_enable <= 0;
					reg_write_lo_enable <= 0;
					imm_enable <= 1;
					imm_value <= tmp_imm_signext << 2;
				end else if (tmp_rt == `INSTRUCTION_RT_BLTZ) begin
					op_type <= `OPERATION_TYPE_BRANCH;
					op_subtype <= `OPERATION_SUBTYPE_LESS;
					reg1_read_enable <= 1;
					reg1_read_addr <= tmp_rs;
					reg1_read_hi_enable <= 0;
					reg1_read_lo_enable <= 0;
					reg2_read_enable <= 0;
					reg2_read_addr <= 0;
					reg_write_enable <= 0;
					reg_write_addr <= 0;
					reg_write_hi_enable <= 0;
					reg_write_lo_enable <= 0;
					imm_enable <= 1;
					imm_value <= tmp_imm_signext << 2;
				end else if (tmp_rt == `INSTRUCTION_RT_BLTZAL) begin
					op_type <= `OPERATION_TYPE_BRANCH;
					op_subtype <= `OPERATION_SUBTYPE_LESS;
					reg1_read_enable <= 1;
					reg1_read_addr <= tmp_rs;
					reg1_read_hi_enable <= 0;
					reg1_read_lo_enable <= 0;
					reg2_read_enable <= 0;
					reg2_read_addr <= 0;
					reg_write_enable <= 1;
					reg_write_addr <= `MIPS_CPU_REGISTER_RA_NO;
					reg_write_hi_enable <= 0;
					reg_write_lo_enable <= 0;
					imm_enable <= 1;
					imm_value <= tmp_imm_signext << 2;
				end else begin
					op_type <= `OPERATION_TYPE_NOP;
					op_subtype <= `OPERATION_SUBTYPE_NOP;
					reg1_read_enable <= 0;
					reg1_read_addr <= 0;
					reg1_read_hi_enable <= 0;
					reg1_read_lo_enable <= 0;
					reg2_read_enable <= 0;
					reg2_read_addr <= 0;
					reg_write_enable <= 0;
					reg_write_addr <= 0;
					reg_write_hi_enable <= 0;
					reg_write_lo_enable <= 0;
					imm_enable <= 0;
					imm_value <= 0;
				end
			end else if (tmp_op == `INSTRUCTION_OP_BGTZ) begin
				op_type <= `OPERATION_TYPE_BRANCH;
				op_subtype <= `OPERATION_SUBTYPE_GREATER;
				reg1_read_enable <= 1;
				reg1_read_addr <= tmp_rs;
				reg1_read_hi_enable <= 0;
				reg1_read_lo_enable <= 0;
				reg2_read_enable <= 0;
				reg2_read_addr <= 0;
				reg_write_enable <= 0;
				reg_write_addr <= 0;
				reg_write_hi_enable <= 0;
				reg_write_lo_enable <= 0;
				imm_enable <= 1;
				imm_value <= tmp_imm_signext << 2;
			end else if (tmp_op == `INSTRUCTION_OP_BLEZ) begin
				op_type <= `OPERATION_TYPE_BRANCH;
				op_subtype <= `OPERATION_SUBTYPE_LESS_EQUAL;
				reg1_read_enable <= 1;
				reg1_read_addr <= tmp_rs;
				reg1_read_hi_enable <= 0;
				reg1_read_lo_enable <= 0;
				reg2_read_enable <= 0;
				reg2_read_addr <= 0;
				reg_write_enable <= 0;
				reg_write_addr <= 0;
				reg_write_hi_enable <= 0;
				reg_write_lo_enable <= 0;
				imm_enable <= 1;
				imm_value <= tmp_imm_signext << 2;
			end else if (tmp_op == `INSTRUCTION_OP_BNE) begin
				op_type <= `OPERATION_TYPE_BRANCH;
				op_subtype <= `OPERATION_SUBTYPE_NOT_EQUAL;
				reg1_read_enable <= 1;
				reg1_read_addr <= tmp_rs;
				reg1_read_hi_enable <= 0;
				reg1_read_lo_enable <= 0;
				reg2_read_enable <= 1;
				reg2_read_addr <= tmp_rt;
				reg_write_enable <= 0;
				reg_write_addr <= 0;
				reg_write_hi_enable <= 0;
				reg_write_lo_enable <= 0;
				imm_enable <= 1;
				imm_value <= tmp_imm_signext << 2;
			end else if (tmp_op == `INSTRUCTION_OP_J) begin
				op_type <= `OPERATION_TYPE_JUMP;
				op_subtype <= `OPERATION_SUBTYPE_NOP;
				reg1_read_enable <= 0;
				reg1_read_addr <= 0;
				reg1_read_hi_enable <= 0;
				reg1_read_lo_enable <= 0;
				reg2_read_enable <= 0;
				reg2_read_addr <= 0;
				reg_write_enable <= 0;
				reg_write_addr <= 0;
				reg_write_hi_enable <= 0;
				reg_write_lo_enable <= 0;
				imm_enable <= 1;
				imm_value <= tmp_j_addr_ext << 2;
			end else if (tmp_op == `INSTRUCTION_OP_JAL) begin
				op_type <= `OPERATION_TYPE_JUMP;
				op_subtype <= `OPERATION_SUBTYPE_NOP;
				reg1_read_enable <= 0;
				reg1_read_addr <= 0;
				reg1_read_hi_enable <= 0;
				reg1_read_lo_enable <= 0;
				reg2_read_enable <= 0;
				reg2_read_addr <= 0;
				reg_write_enable <= 1;
				reg_write_addr <= `MIPS_CPU_REGISTER_RA_NO;
				reg_write_hi_enable <= 0;
				reg_write_lo_enable <= 0;
				imm_enable <= 1;
				imm_value <= tmp_j_addr_ext << 2;
			end else if (tmp_op == `INSTRUCTION_OP_ANDI) begin
				op_type <= `OPERATION_TYPE_ALU;
				op_subtype <= `OPERATION_SUBTYPE_AND;
				reg1_read_enable <= 1;
				reg1_read_addr <= tmp_rs;
				reg1_read_hi_enable <= 0;
				reg1_read_lo_enable <= 0;
				reg2_read_enable <= 0;
				reg2_read_addr <= 0;
				reg_write_enable <= 1;
				reg_write_addr <= tmp_rt;
				reg_write_hi_enable <= 0;
				reg_write_lo_enable <= 0;
				imm_enable <= 1;
				imm_value <= tmp_imm_zeroext;
			end else if (tmp_op == `INSTRUCTION_OP_LUI) begin
				op_type <= `OPERATION_TYPE_ALU;
				op_subtype <= `OPERATION_SUBTYPE_GET;
				reg1_read_enable <= 0;
				reg1_read_addr <= 0;
				reg1_read_hi_enable <= 0;
				reg1_read_lo_enable <= 0;
				reg2_read_enable <= 0;
				reg2_read_addr <= 0;
				reg_write_enable <= 1;
				reg_write_addr <= tmp_rt;
				reg_write_hi_enable <= 0;
				reg_write_lo_enable <= 0;
				imm_enable <= 1;
				imm_value <= tmp_imm_zeroext << 16;
			end else if (tmp_op == `INSTRUCTION_OP_ORI) begin
				op_type <= `OPERATION_TYPE_ALU;
				op_subtype <= `OPERATION_SUBTYPE_OR;
				reg1_read_enable <= 1;
				reg1_read_addr <= tmp_rs;
				reg1_read_hi_enable <= 0;
				reg1_read_lo_enable <= 0;
				reg2_read_enable <= 0;
				reg2_read_addr <= 0;
				reg_write_enable <= 1;
				reg_write_addr <= tmp_rt;
				reg_write_hi_enable <= 0;
				reg_write_lo_enable <= 0;
				imm_enable <= 1;
				imm_value <= tmp_imm_zeroext;
			end else if (tmp_op == `INSTRUCTION_OP_XORI) begin
				op_type <= `OPERATION_TYPE_ALU;
				op_subtype <= `OPERATION_SUBTYPE_XOR;
				reg1_read_enable <= 1;
				reg1_read_addr <= tmp_rs;
				reg1_read_hi_enable <= 0;
				reg1_read_lo_enable <= 0;
				reg2_read_enable <= 0;
				reg2_read_addr <= 0;
				reg_write_enable <= 1;
				reg_write_addr <= tmp_rt;
				reg_write_hi_enable <= 0;
				reg_write_lo_enable <= 0;
				imm_enable <= 1;
				imm_value <= tmp_imm_zeroext;
			end else begin
				op_type <= `OPERATION_TYPE_NOP;
				op_subtype <= `OPERATION_SUBTYPE_NOP;
				reg1_read_enable <= 0;
				reg1_read_addr <= 0;
				reg1_read_hi_enable <= 0;
				reg1_read_lo_enable <= 0;
				reg2_read_enable <= 0;
				reg2_read_addr <= 0;
				reg_write_enable <= 0;
				reg_write_addr <= 0;
				reg_write_hi_enable <= 0;
				reg_write_lo_enable <= 0;
				imm_enable <= 0;
				imm_value <= 0;
			end
		end else begin
			op_type <= `OPERATION_TYPE_NOP;
			op_subtype <= `OPERATION_SUBTYPE_NOP;
			reg1_read_enable <= 0;
			reg1_read_addr <= 0;
			reg1_read_hi_enable <= 0;
			reg1_read_lo_enable <= 0;
			reg2_read_enable <= 0;
			reg2_read_addr <= 0;
			reg_write_enable <= 0;
			reg_write_addr <= 0;
			reg_write_hi_enable <= 0;
			reg_write_lo_enable <= 0;
			imm_enable <= 0;
			imm_value <= 0;
		end
	end
	
endmodule
